package com.chap6;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * <p>
 * <code>CyclicBarrierBatchProcessorDemo</code>
 * </p>
 *
 * @author junbao3
 * TODO
 * @date 2023-03-20 5:41
 * Copyright (C) 2021 IFlyTek. All rights reserved.
 */
public class CyclicBarrierBatchProcessorDemo {
    public static void main(String[] args) {
        //生成数据 任务分工
        List<Integer> data = new ArrayList<>();
        for (int i = 1; i <=50 ; i++) {
            data.add(i);
        }

        //指定数据处理大小
        int batchSize = 5;
        CycliBarrierBatchProcessor processor = new CycliBarrierBatchProcessor(data,batchSize);
        processor.process(batchData -> {
            for (Integer i:batchData){
                System.out.println(Thread.currentThread().getName()+"处理数据"+i);
            }
        });
    }
}

class CycliBarrierBatchProcessor{
    private List<Integer> data;//需要处理的数据
    private int batchSize;//每一次处理数据的大小
    private CyclicBarrier barrier;
    private List<Thread> threads;//没啥用

    public CycliBarrierBatchProcessor(List<Integer> data, int batchSize) {
        this.data = data;
        this.batchSize = batchSize;
        this.barrier = new CyclicBarrier(batchSize);
        this.threads = new ArrayList<>();
    }

    public void process(BatchTask task){
        int threadCount = (data.size()+batchSize-1)/batchSize;
        for (int i = 0; i < threadCount; i++) {
            int start = i*batchSize;
            int end = Math.min(start+batchSize,data.size());
            List<Integer> batchData = data.subList(start, end);
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    task.process(batchData);
                    try {
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            });
            threads.add(thread);
            thread.start();

        }
    }

    public interface  BatchTask{
        void process(List<Integer> batchData);
    }
}
